package com.falm.picturebackend.service.impl;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import com.falm.picturebackend.entity.BO.UserBO;
import com.falm.picturebackend.entity.DTO.*;
import com.falm.picturebackend.entity.common.PageRequest;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.falm.picturebackend.entity.VO.UserVO;
import com.falm.picturebackend.entity.convert.UserConvert;
import com.falm.picturebackend.entity.factory.UserFactory;
import com.falm.picturebackend.exception.ErrorCode;
import com.falm.picturebackend.exception.ThrowUtils;
import com.falm.picturebackend.repository.UserRepository;
import com.falm.picturebackend.service.UserService;
import com.falm.picturebackend.util.JWTUtil;
import com.falm.picturebackend.util.SecurityUtil;
import com.falm.picturebackend.util.TokenBlackListUtil;
import com.falm.picturebackend.util.ValidUtil;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class UserServiceImpl implements UserService {

    @Value("${user.default.password}")
    private static final String DEFAULT_PASSWORD = "111111";

    @Resource
    private UserRepository userRepository;

    @Override
    public void userRegister(UserRegisterDTO userRegisterDTO) {
        // 校验是否参数为空
        ThrowUtils.throwIf(ValidUtil.validHasBlank(userRegisterDTO.getUserAccount(), userRegisterDTO.getUserPassword(),
            userRegisterDTO.getUserConfirmPassword(), userRegisterDTO.getUserName()), ErrorCode.PARAMS_ERROR);
        // 校验登陆账号长度是否合理
        ThrowUtils.throwIf(!ValidUtil.validLength(1, 20, userRegisterDTO.getUserAccount()), ErrorCode.PARAMS_ERROR);
        // 校验密码长度是否合理
        ThrowUtils.throwIf(
            !ValidUtil.validLength(6, 20, userRegisterDTO.getUserPassword(), userRegisterDTO.getUserConfirmPassword()),
            ErrorCode.PARAMS_ERROR, "密码长度需要在{0}到{1}位之间", 6, 20);
        // 校验用户密码和确认密码是否一致，不一致则失败
        ThrowUtils.throwIf(!userRegisterDTO.getUserPassword().equals(userRegisterDTO.getUserConfirmPassword()),
            ErrorCode.PARAMS_ERROR, "两次输入密码不一致");
        // 校验该账户是否已存在
        UserBO userBO = userRepository.getUserByUserAccount(userRegisterDTO.getUserAccount());
        ThrowUtils.throwIf(!ObjectUtils.isEmpty(userBO), ErrorCode.PARAMS_ERROR, "账户已存在");

        // 根据基础信息创建一个基础用户
        userBO = UserFactory.createUser(userRegisterDTO);

        // 对密码加密
        userBO.setUserPassword(SecurityUtil.encrypt(userBO.getUserPassword()));

        userRepository.addUser(userBO);
    }

    @Override
    public String userLogin(UserLoginDTO userLoginDTO) {
        ThrowUtils.throwIf(ValidUtil.validHasBlank(userLoginDTO.getUserAccount(), userLoginDTO.getUserPassword()),
            ErrorCode.PARAMS_ERROR);

        // 对密码进行加密
        UserBO userBO = userRepository.getUserByUserAccount(userLoginDTO.getUserAccount());
        ThrowUtils.throwIf(
            ObjectUtils.isEmpty(userBO) || !SecurityUtil.verify(userBO.getUserPassword(), userLoginDTO.getUserPassword()),
            ErrorCode.PARAMS_ERROR, "用户名或密码错误");

        return JWTUtil.createJwt(UserConvert.bo2VO(userBO));
    }

    @Override
    public UserVO getLoginUser(HttpServletRequest request) {
        ThrowUtils.throwIf(ObjectUtils.isEmpty(getToken(request)), ErrorCode.NOT_LOGIN_ERROR);
        ThrowUtils.throwIf(!JWTUtil.verifyJwt(getToken(request)), ErrorCode.NOT_LOGIN_ERROR);
        return JWTUtil.parseJwtGetUserInfo(getToken(request));
    }

    @Override
    public void logout(HttpServletRequest request) {

        // 将token加入黑名单
        TokenBlackListUtil.addToBlackList(getToken(request));

    }

    @Override
    public void addUser(UserAddDTO userAddDTO) {
        // 校验是否参数为空
        ThrowUtils.throwIf(ValidUtil.validHasBlank(userAddDTO.getUserAccount()), ErrorCode.PARAMS_ERROR);
        if (StringUtils.isBlank(userAddDTO.getUserPassword())) {
            userAddDTO.setUserPassword(SecurityUtil.encrypt(DEFAULT_PASSWORD));
        } else {
            userAddDTO.setUserPassword(SecurityUtil.encrypt(userAddDTO.getUserPassword()));
        }
        userRepository.addUser(UserFactory.createUser(userAddDTO));
    }

    @Override
    public void deleteUser(UserDeleteDTO userDeleteDTO) {
        String userAccount = userDeleteDTO.getUserAccount();
        ThrowUtils.throwIf(StringUtils.isBlank(userAccount), ErrorCode.PARAMS_ERROR);
        UserBO userByUserBOAccount = userRepository.getUserByUserAccount(userAccount);
        ThrowUtils.throwIf(ObjectUtils.isEmpty(userByUserBOAccount), ErrorCode.NOT_FOUND_ERROR);
        userRepository.deleteUser(userAccount);
    }

    @Override
    public void updateUser(UserUpdateDTO userUpdateDTO) {
        ThrowUtils.throwIf(ValidUtil.validHasBlank(userUpdateDTO.getUserAccount()), ErrorCode.PARAMS_ERROR);
        UserBO userBO = userRepository.getUserByUserAccount(userUpdateDTO.getUserAccount());
        ThrowUtils.throwIf(ObjectUtils.isEmpty(userBO), ErrorCode.NOT_FOUND_ERROR);
        userRepository.updateUser(UserFactory.createUser(userUpdateDTO));

    }

    @Override
    public PageInfo<UserVO> getUser(PageRequest<UserGetDTO> userGetDTOPageRequest) {
        PageHelper.startPage(userGetDTOPageRequest.getCurrent(), userGetDTOPageRequest.getPageSize());
        UserBO userBO = UserFactory.createUser(userGetDTOPageRequest.getData());
        List<UserBO> userBOList =
            userRepository.getUser(userBO, userGetDTOPageRequest.getSortField(), userGetDTOPageRequest.getSortOrder());
        List<UserVO> userVOList = userBOList.stream().map(UserConvert::bo2VO).collect(Collectors.toList());
        return new PageInfo<>(userVOList);
    }

    private static String getToken(HttpServletRequest request) {
        return request.getHeader("token");
    }
}
